<template>
  <el-container>
    <el-header>
      <el-steps :active="step" finish-status="success" :align-center="true" style="width: 90%; margin: 20px auto">
        <el-step title="基本信息"></el-step>
        <el-step title="规格参数"></el-step>
        <el-step title="销售属性"></el-step>
        <el-step title="SKU信息"></el-step>
        <el-step title="保存完成"></el-step>
      </el-steps>
    </el-header>
    <el-main>
      <div v-show="step === 0">
        <el-card class="box-card" style="width: 80%; margin: 20px auto">
          <el-form ref="basisInfoDataFormRef" :model="dataForm" label-width="160px" :rules="dataRule">
            <el-form-item label="商品名称" prop="name">
              <el-input v-model="dataForm.name" minlength="2" maxlength="50" show-word-limit></el-input>
            </el-form-item>
            <el-form-item label="商品描述" prop="desct">
              <el-input type="textarea" v-model="dataForm.desct" minlength="2" maxlength="512" show-word-limit></el-input>
            </el-form-item>
            <el-form-item label="商品品牌" prop="brandId">
              <el-col :span="10">
                <category-cascader v-model="temp.categoryIds" />
              </el-col>
              <el-col class="line" :span="4" style="text-align: center">-</el-col>
              <el-col :span="10">
                <brand-select v-model="dataForm.brandId" :category-id="dataForm.categoryId" />
              </el-col>
            </el-form-item>
            <el-form-item label="商品重量(Kg)" prop="weight">
              <el-input-number v-model.number="dataForm.weight" :min="0" :precision="3" :step="0.1" style="width: 100%" />
            </el-form-item>
            <el-form-item label="设置金币" prop="bounds">
              <el-col :span="10" style="text-align: center">
                <el-input-number v-model="dataForm.bounds.buyBounds" :min="0" controls-position="right" style="width: 100%" />
              </el-col>
              <el-col :span="4" style="text-align: center"> 成长值 </el-col>
              <el-col :span="10">
                <el-input-number v-model="dataForm.bounds.growBounds" :min="0" controls-position="right" style="width: 100%" />
              </el-col>
            </el-form-item>
            <el-form-item label="商品图集" prop="images">
              <list-upload v-model="dataForm.images" :limit="100"></list-upload>
            </el-form-item>
            <el-form-item label="商品介绍" prop="introduce">
              <list-upload v-model="dataForm.introduce" :limit="50"></list-upload>
            </el-form-item>
            <el-form-item>
              <el-button type="success" @click="collectSpuInfoNextStep(basisInfoDataFormRef)">下一步：设置基本参数</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
      <div v-show="step === 1">
        <el-card class="box-card" style="width: 80%; margin: 20px auto">
          <el-tabs tab-position="left" style="height: 400px">
            <!-- 遍历属性，每个分组对应一个表单，每个属性对应一个表单项 -->
            <el-tab-pane :label="group.name" v-for="(group, gidx) in dataRespond.attrgroups" :key="group.id">
              <el-form :model="dataForm" label-width="180px">
                <el-form-item :label="attr.name" v-for="(attr, aidx) in group.attrs" :key="attr.id">
                  <el-col :span="10">
                    <el-input v-model="temp.baseAttrs[gidx][aidx].id" type="hidden" v-show="false"></el-input>
                    <el-select
                      v-model="temp.baseAttrs[gidx][aidx].options"
                      :multiple="attr.multiple === 1"
                      style="width: 100%"
                      filterable
                      allow-create
                      default-first-option
                      placeholder="请选择或输入值"
                    >
                      <el-option v-for="(val, vidx) in attr.options.split(';')" :key="vidx" :label="val" :value="val"></el-option>
                    </el-select>
                  </el-col>
                  <el-col :span="4" style="text-align: center">
                    <el-checkbox v-model="temp.baseAttrs[gidx][aidx].visible" :true-label="1" :false-label="0">快速展示</el-checkbox>
                  </el-col>
                </el-form-item>
              </el-form>
            </el-tab-pane>
          </el-tabs>
          <div class="bottom">
            <el-button type="primary" @click="step = 0">上一步</el-button>
            <el-button type="success" @click="collectBaseAttrsNextStep">下一步：设置销售属性</el-button>
          </div>
        </el-card>
      </div>
      <div v-show="step === 2">
        <el-card class="box-card" style="width: 80%; margin: 20px auto">
          <div slot="header" class="clearfix">
            <el-form ref="saleform" :model="dataForm" label-width="120px" label-position="left">
              <el-form-item :label="attr.name" v-for="(attr, aidx) in dataRespond.saleAttrs" :key="attr.id">
                <el-input v-model="temp.saleAttrs[aidx].id" type="hidden" v-show="false" />
                <el-checkbox-group v-model="temp.saleAttrs[aidx].options" style="display: contents;">
                  <template v-if="dataRespond.saleAttrs[aidx].options !== ''">
                    <el-checkbox :label="val" v-for="val in dataRespond.saleAttrs[aidx].options.split(';')" :key="val" />
                  </template>
                  <div style="margin-left: 20px;">
                    <el-button v-show="!temp.saleAttrs[aidx].input.visible" class="button-new-tag" size="small" @click="showSaleAttrInput(aidx)">+自定义</el-button>
                    <el-input
                      v-show="temp.saleAttrs[aidx].input.visible"
                      v-model="temp.saleAttrs[aidx].input.value"
                      size="small"
                      style="width: 150px"
                      @keyup.enter.native="handleSaleAttrInputConfirm(aidx)"
                      @blur="handleSaleAttrInputConfirm(aidx)"
                    ></el-input>
                  </div>
                </el-checkbox-group>
              </el-form-item>
            </el-form>
          </div>
          <div class="bottom">
            <el-button type="primary" @click="step = 1">上一步</el-button>
            <el-button type="success" @click="collectSaleAttrsNextStep">下一步：设置SKU信息</el-button>
          </div>
        </el-card>
      </div>
      <div v-show="step === 3">
        <el-card class="box-card" style="width: 80%; margin: 20px auto">
          <el-table :data="dataForm.skus" style="width: 100%">
            <el-table-column label="属性组合">
              <el-table-column :label="item.name" v-for="(item, index) in temp.tableAttrColumn" :key="item.id">
                <template #default="scope">
                  <span style="margin-left: 10px">{{ scope.row.attrs[index].options }}</span>
                </template>
              </el-table-column>
            </el-table-column>
            <el-table-column label="商品名称" prop="name">
              <template #default="scope">
                <el-input v-model="scope.row.name"></el-input>
              </template>
            </el-table-column>
            <el-table-column label="标题" prop="title">
              <template #default="scope">
                <el-input v-model="scope.row.title"></el-input>
              </template>
            </el-table-column>
            <el-table-column label="副标题" prop="subtitle">
              <template #default="scope">
                <el-input v-model="scope.row.subtitle"></el-input>
              </template>
            </el-table-column>
            <el-table-column label="价格" prop="price">
              <template #default="scope">
                <el-input v-model="scope.row.price"></el-input>
              </template>
            </el-table-column>
            <el-table-column type="expand">
              <template #default="scope">
                <fieldset style="margin: 10px;">
                  <legend>编辑商品[{{ scope.row.name }}]信息</legend>
                  <!-- 折扣，满减，会员价 -->
                  <el-form :model="scope.row" label-width="120px" class="bounds-form">
                    <el-form-item label="选择图集">
                      <el-col :span="24">
                        <list-upload v-model="temp.images" btn-name="上传更多图集" :show-tip="false" :show-file-list="false" list-type="text" />
                      </el-col>
                      <el-col :span="24">
                        <el-card style="width: 160px; float: left; margin-top: 15px; margin-right: 15px" :body-style="{ padding: '0px' }" v-for="(img, index) in dataForm.images" :key="index">
                          <el-image style="width: 140px; height: 140px; margin: auto 10px" :src="img" fit="fill"></el-image>
                          <div>
                            <el-row>
                              <el-col :span="12">
                                <el-checkbox style="margin-left: 15px" v-model="scope.row.images[index].url" :true-label="img" false-label />
                              </el-col>
                              <el-col :span="12">
                                <el-tag size="small" v-if="scope.row.images[index].isDefault === 1">
                                  <el-radio type="radio" checked :name="scope.row.name" :value="1" :label="1" @change="checkDefaultImage(scope.row, index, img)">默认</el-radio>
                                </el-tag>
                                <el-tag size="small" v-else>
                                  <el-radio type="radio" :name="scope.row.name" :value="1" :label="0" @change="checkDefaultImage(scope.row, index, img)">默认</el-radio>
                                </el-tag>
                              </el-col>
                            </el-row>
                          </div>
                        </el-card>
                      </el-col>
                      <el-col :span="24">
                        <el-divider></el-divider>
                      </el-col>
                    </el-form-item>
                    <el-form-item label="设置折扣">
                      <el-col class="label" :span="2">
                        <label>满</label>
                      </el-col>
                      <el-col :span="6">
                        <el-input-number style="width: 100%" :min="0" v-model="scope.row.fullcount" />
                      </el-col>
                      <el-col class="label" :span="2">
                        <label>件</label>
                      </el-col>
                      <el-col class="label" :span="2">
                        <label>打</label>
                      </el-col>
                      <el-col :span="6">
                        <el-input-number style="width: 100%" v-model="scope.row.discount" :precision="2" :max="1" :min="0" :step="0.01" />
                      </el-col>
                      <el-col class="label" :span="2">
                        <label>折</label>
                      </el-col>
                      <el-col :span="4">
                        <el-checkbox v-model="scope.row.countSuperposable" :true-label="1" :false-label="0">可叠加优惠</el-checkbox>
                      </el-col>
                    </el-form-item>
                    <el-form-item label="设置满减">
                      <el-col class="label" :span="2">
                        <label>满</label>
                      </el-col>
                      <el-col :span="6">
                        <el-input-number style="width: 100%" v-model="scope.row.fullPrice" :step="100" :min="0" />
                      </el-col>
                      <el-col class="label" :span="2">
                        <label>元</label>
                      </el-col>
                      <el-col class="label" :span="2">
                        <label>减</label>
                      </el-col>
                      <el-col :span="6">
                        <el-input-number style="width: 100%" v-model="scope.row.reducePrice" :step="10" :min="0" />
                      </el-col>
                      <el-col class="label" :span="2">
                        <label>元</label>
                      </el-col>
                      <el-col :span="4">
                        <el-checkbox v-model="scope.row.priceSuperposable" :true-label="1" :false-label="0">可叠加优惠</el-checkbox>
                      </el-col>
                    </el-form-item>
                    <el-form-item v-if="scope.row.memberPrice.length > 0" label="设置会员价" class="member-price-box">
                      <el-row v-for="(mp, mpidx) in scope.row.memberPrice" :key="mp.id">
                        <el-col :span="4">
                          <label>{{ mp.name }}</label>
                        </el-col>
                        <el-col :span="8">
                          <el-input-number style="width: 160px" v-model="scope.row.memberPrice[mpidx].price" :precision="2" :min="0" controls-position="right" />
                        </el-col>
                        <el-col :span="4">
                          <el-checkbox v-model="scope.row.memberPrice[mpidx].superposable" :true-label="1" :false-label="0">可叠加优惠</el-checkbox>
                        </el-col>
                      </el-row>
                    </el-form-item>
                  </el-form>
                </fieldset>
              </template>
            </el-table-column>
          </el-table>
          <div class="bottom">
            <el-button type="primary" @click="step = 2">上一步</el-button>
            <el-button v-if="admin.isAuth('product:spu:save')" type="success" @click="submitSkuDataForm" :loading="submitted">
              {{ submitted ? "数据提交中，请耐心等待~~~" : "下一步：保存商品信息" }}
            </el-button>
          </div>
        </el-card>
      </div>
      <div v-show="step === 4">
        <el-card class="box-card" style="width: 80%; margin: 20px auto">
          <h1>保存成功</h1>
          <el-button type="primary" @click="continueToAdd">继续添加</el-button>
        </el-card>
      </div>
    </el-main>
  </el-container>
</template>

<script lang="ts" setup>
import admin from "@/utils/admin";
import http from "@/utils/httpRequest";
import criteria from "@/utils/criteria";
import validate from "@/utils/validate";
import { ElMessage, ElMessageBox, FormInstance } from "element-plus";
import { ref, reactive, watch, onMounted } from "vue";

import BrandSelect from "../common/brand-select.vue";
import CategoryCascader from "../common/category-cascader.vue";
import ListUpload from "@/components/upload/list-upload.vue";

// 当前流程步骤
const step = ref(0);

// 是否提交
const submitted = ref(false);

// 表单提交数据
const dataForm = reactive({
  id: undefined,
  name: "",
  desct: "",
  weight: 0,
  published: 0,
  brandId: "",
  categoryId: "",
  // 商品介绍，都是上传大图
  introduce: [],
  // 商品图集，最后 SKU 也可以新增
  images: [],
  // 优惠卷
  bounds: {
    buyBounds: 0,
    growBounds: 0,
  },
  // 规则参数
  baseAttrs: [],
  // 所有 SKU 信息
  skus: [],
});

// 表单验证
const dataRule = reactive({
  name: validate.required("商品名称"),
  desct: validate.required("商品描述"),
  categoryId: validate.required("商品分类"),
  brandId: validate.required("商品品牌"),
  weight: validate.required("商品重量"),
  images: { required: true, message: "请上传商品图片集", trigger: "blur" },
  introduce: { required: true, message: "请上传商品介绍图集", trigger: "blur" },
});

// 临时数据
const temp = reactive({
  baseAttrs: [],
  saleAttrs: [],
  tableAttrColumn: [],
  categoryIds: [],
  images: [],
});

// 后台返回的所有数据
const dataRespond = reactive({
  attrgroups: [],
  saleAttrs: [],
  memberLevels: [],
  steped: [false, false, false, false, false],
});

// 基本信息表单引用
const basisInfoDataFormRef = ref<FormInstance>();

// 监控最后一步上传更多图集
watch(() => temp.images, (val) => {
  // 扩展每个 skus 里面的 images 选项
  let imgArr = Array.from(new Set(dataForm.images.concat(val)));
  // 由于concat每次迭代上次，有很多重复。所以我们必须得到上次+这次的总长
  dataForm.skus.forEach((item, index) => {
    let len = imgArr.length - dataForm.skus[index].images.length;
    if (len > 0) {
      let imgs = new Array(len);
      imgs = imgs.fill({ url: "", isDefault: 0 });
      dataForm.skus[index].images = item.images.concat(imgs);
    }
  });
  dataForm.images = imgArr;
});

// 监控商品分组级联选择
watch(() => temp.categoryIds, (val) => {
  if (val && val.length > 0) {
    dataForm.categoryId = val[val.length - 1];
    dataRespond.steped = [false, false, false, false, false];
  }
});

// 组件挂载完成后执行
onMounted(() => {
  loadMemberLevels();
});

// 加载会员等级
const loadMemberLevels = () => {
  http
    .post({
      url: "/member/level/list",
    })
    .then(({ data }) => {
      dataRespond.memberLevels = data.body;
    });
};

// 商品基本信息采集完成处理，跳转下一步
const collectSpuInfoNextStep = (form: FormInstance | undefined) => {
  form.validate((valid) => {
    if (valid) {
      step.value = 1;
      loadAttrgroupsData();
    }
  });
};

// 加载属性分组信息
const loadAttrgroupsData = () => {
  if (!dataRespond.steped[0]) {
    http
      .post({
        url: `/product/attrgroup/list-attach-attr?categoryId=${dataForm.categoryId}`,
      })
      .then(({ data }) => {
        if (http.success(data)) {
          let list = data.body;
          if (!list || list.length === 0) {
            ElMessage.warning("未查询到商品分类所属规格参数，请先维护分类下的规格参数！");
            return;
          }
          // 先对表单的 baseAttrs 进行初始化
          list.forEach((item) => {
            let attrArray = [];
            item.attrs.forEach((attr) => {
              attrArray.push({
                id: attr.id,
                options: "",
                visible: attr.visible,
              });
            });
            temp.baseAttrs.push(attrArray);
          });
          dataRespond.steped[0] = true;
          dataRespond.attrgroups = list;
        }
      });
  }
};

// 规则参数采集完成处理，跳转下一步
const collectBaseAttrsNextStep = () => {
  // 把规则参数表单数据绑定到 dataForm.baseAttrs，这是最终要提交的数据
  dataForm.baseAttrs = [];
  temp.baseAttrs.forEach((item) => {
    item.forEach((attr) => {
      let { id, options, visible } = attr;
      // 跳过没有录入值的属性
      if (options instanceof Array && options.length > 0) {
        options = options.join(";");
        dataForm.baseAttrs.push({ id, options, visible });
      } else if (typeof options === "string" && options) {
        dataForm.baseAttrs.push({ id, options, visible });
      }
    });
  });
  // 规则参数不能为空
  if (dataForm.baseAttrs.length <= 0) {
    ElMessage.warning("请先设置规格参数，再进行下一步操作！");
    return;
  }
  // 跳转设置销售属性
  step.value = 2;
  loadSaleAttrsData();
};

// 加载销售属性数据
const loadSaleAttrsData = () => {
  // 获取当前分类可以使用的销售属性
  if (!dataRespond.steped[1]) {
    http
      .post({
        url: `/product/attr/select?type=0`,
        data: {
          current: 1,
          size: 100,
          criterias: [criteria.eq("categoryId", dataForm.categoryId), criteria.eq("type", 0)],
        },
      })
      .then(({ data }) => {
        if (http.success(data)) {
          // 初始化销售属性的表单数据
          temp.saleAttrs = [];
          data.body.records.forEach((item) => {
            temp.saleAttrs.push({
              id: item.id,
              options: [],
              name: item.name,
              // 自定义内容
              input: {
                value: "",
                visible: false,
              },
            });
            dataRespond.saleAttrs = data.body.records;
          });
          dataRespond.steped[1] = true;
        }
      });
  }
};

// 显示销售属性输入框
const showSaleAttrInput = (idx) => {
  temp.saleAttrs[idx].input.visible = true;
};

// 销售属性自定义内容确认
const handleSaleAttrInputConfirm = (idx) => {
  let inputValue = temp.saleAttrs[idx].input.value;
  if (inputValue) {
    dataRespond.saleAttrs[idx].options += (dataRespond.saleAttrs[idx].options ? ";" : "") + inputValue;
  }
  temp.saleAttrs[idx].input.value = "";
  temp.saleAttrs[idx].input.visible = false;
};

// 采集销售属性完成处理，跳转下一步
const collectSaleAttrsNextStep = () => {
  step.value = 3;
  // 通过销售属性，生成属性组合列
  let selectValues = [];
  temp.tableAttrColumn = [];
  temp.saleAttrs.forEach((item) => {
    if (item.options.length > 0) {
      selectValues.push(item.options);
      temp.tableAttrColumn.push(item);
    }
  });
  // 通过销售属性，根据笛卡尔积运算进行生成 SKU 信息
  let descartes = createDescartes(selectValues);
  // 有多少descartes就有多少sku
  let skus = [];
  descartes.forEach((descar, descaridx) => {
    // sku 属性组
    let attrArray = [];
    descar.forEach((de, index) => {
      // 构造saleAttr信息
      let item = {
        id: temp.tableAttrColumn[index].id,
        name: temp.tableAttrColumn[index].name,
        options: de,
      };
      attrArray.push(item);
    });
    // 先初始化几个images，后面的上传还要加
    let imgs = [];
    dataForm.images.forEach((img, idx) => {
      imgs.push({ url: "", isDefault: 0 });
    });
    // 会员价，也必须在循环里面生成，否则会导致数据绑定问题
    let memberPrices = [];
    if (dataRespond.memberLevels.length > 0) {
      for (let i = 0; i < dataRespond.memberLevels.length; i++) {
        if (dataRespond.memberLevels[i].priviledgeMemberPrice === 1) {
          memberPrices.push({
            id: dataRespond.memberLevels[i].id,
            name: dataRespond.memberLevels[i].name,
            price: 0,
            superposable: 0,
          });
        }
      }
    }
    // descaridx，判断如果之前有就用之前的值;
    let res = hasAndReturnSku(dataForm.skus, descar);
    if (res === null) {
      skus.push({
        attrs: attrArray,
        name: dataForm.name + " " + descar.join(" "),
        title: dataForm.name + " " + descar.join(" "),
        subtitle: "",
        price: 0,
        images: imgs,
        descar: descar,
        fullcount: 0,
        discount: 0,
        countSuperposable: 0,
        fullPrice: 0.0,
        reducePrice: 0.0,
        priceSuperposable: 0,
        memberPrice: [].concat(memberPrices),
      });
    } else {
      skus.push(res);
    }
  });
  dataForm.skus = skus;
};

// 判断如果包含之前的sku的descar组合，就返回这个sku的详细信息
const hasAndReturnSku = (skus, descar) => {
  let res = null;
  if (skus.length > 0) {
    for (let i = 0; i < skus.length; i++) {
      if (skus[i].descar.join(" ") === descar.join(" ")) {
        res = skus[i];
      }
    }
  }
  return res;
};

// 设置默认图片
const checkDefaultImage = (row, index, img) => {
  // 这个图片被选中了，
  row.images[index].url = img; // 默认选中
  row.images[index].isDefault = 1; // 修改标志位
  // 修改其他人的标志位
  row.images.forEach((item, idx) => {
    if (idx !== index) {
      row.images[idx].isDefault = 0;
    }
  });
};

// 提交商品数据
const submitSkuDataForm = () => {
  if (submitted.value) {
    return;
  }
  console.log("提交SPU数据：", JSON.stringify(dataForm));
  ElMessageBox.confirm("将要提交商品数据，需要一小段时间，是否继续?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
  .then(() => {
    submitted.value = true;
    http
      .instance({
        url: http.adornUrl("/product/spu/save"),
        method: "post",
        data: http.adornData(dataForm, false),
      })
      .then(({ data }) => {
        if (http.success(data)) {
          ElMessage.success("新增商品成功!");
          step.value = 4;
        }
        submitted.value = false;
      });
  })
  .catch((e) => {
    ElMessage.info("已取消");
  });
};

// 继续添加
const continueToAdd = () => {
  step.value = 0;
  resetSkuDataForm();
};

// 清空数据
const resetSkuDataForm = () => {
  // 表单提交数据
  dataForm.id = undefined;
  dataForm.name = "";
  dataForm.desct = "";
  dataForm.weight = 0;
  dataForm.published = 0;
  dataForm.brandId = "";
  dataForm.categoryId = "";
  dataForm.introduce = [];
  dataForm.images = [];
  dataForm.bounds = {
    buyBounds: 0,
    growBounds: 0,
  };
  dataForm.baseAttrs = [];
  dataForm.skus = [];
  // 临时数据
  temp.baseAttrs = [];
  temp.saleAttrs = [];
  temp.tableAttrColumn = [];
  temp.categoryIds = [];
  temp.images = [];
  // 后台返回的所有数据
  dataRespond.attrgroups = [];
  dataRespond.saleAttrs = [];
  dataRespond.memberLevels = [];
  dataRespond.steped = [false, false, false, false, false];
};

// 笛卡尔积运算
const createDescartes = (list) => {
  // parent 上一级索引，count 指针计数
  const point = {};
  const result = [];
  let pIndex = null;
  let tempCount = 0;
  let temp = [];
  // 根据参数列生成指针对象
  for (let index in list) {
    if (typeof list[index] === "object") {
      point[index] = { parent: pIndex, count: 0 };
      pIndex = index;
    }
  }
  // 单维度数据结构直接返回
  if (pIndex == null) {
    return list;
  }
  // 动态生成笛卡尔积
  while (true) {
    let index;
    for (index in list) {
      tempCount = point[index]["count"];
      temp.push(list[index][tempCount]);
    }
    // 压入结果数组
    result.push(temp);
    temp = [];
    // 检查指针最大值问题
    while (true) {
      if (point[index]["count"] + 1 >= list[index].length) {
        point[index]["count"] = 0;
        pIndex = point[index]["parent"];
        if (pIndex == null) {
          return result;
        }
        // 赋值 parent 进行再次检查
        index = pIndex;
      } else {
        point[index]["count"]++;
        break;
      }
    }
  }
};
</script>
<style scoped>
.bottom {
  margin: 20px auto;
  line-height: 12px;
}
.bounds-form .label {
  text-align: center;
}
.member-price-box .el-row {
  margin-bottom: 10px;
}
fieldset {
  border: 1px solid #dddddd;
}
</style>
